/*
 * Formula Parser
 * @Version: revised version for ABSL
 * @Revised by Hao Ji
 */

package parser;

import java.util.*;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



public class ParsedFormula extends ParsedUnit {
	private static Logger logger=Logger.getLogger("simwave.converter.parser");

	private static final boolean withUnits=false;
	private static final String prefix="&VAR=";
	private List<String> init;
	private List<String> def;
	private List<String> initVars=new Vector<String>();
	private List<String> defVars=new Vector<String>();
       

	public void parseFormula() throws ParseException{
		if(get(Parser.SIMULATION_UNIT_INIT)!=null){
			init=new Vector<String>();
			parse(Parser.SIMULATION_UNIT_INIT,init,initVars);
		}
		if(get(Parser.SIMULATION_UNIT_DEF)!=null){
			def=new Vector<String>();
			parse(Parser.SIMULATION_UNIT_DEF,def,defVars);
		}
	}
	public List<String> getVariables(String name){
		if(name.equals(Parser.SIMULATION_UNIT_DEF))
			return defVars;
		if(name.equals(Parser.SIMULATION_UNIT_INIT))
			return initVars;
		return null;
	}
public String maxOperate(String operand) throws ParseException{
    String op;
    String[] operanden=intelliSplit(operand,',');
                                        
					op="if("+operanden[0]+">"+operanden[1]+")";
					op=op+"{ return ,"+operanden[0]+",; }";
					op=op+"else{ return ,"+operanden[1]+",; }";
    return op;
    
}
public String minOperate(String operand)throws ParseException{
      String op;
    String[] operanden=intelliSplit(operand,',');
                                        
					op="if("+operanden[0]+"<"+operanden[1]+")";
					op=op+"{ return "+operanden[0]+"; }";
					op=op+"else{ return "+operanden[1]+"; }";
    return op;
}
	public void evaluate(Hashtable<String,ParsedUnit> units, Hashtable<String,ParsedUnit> model) throws ParseException{
 
                System.out.println("\n");
		System.out.println("NAME\t"+get(Parser.SIMULATION_UNIT_NAME));
		if(init!=null){
                    System.out.println("Initial Formula\t"+get(Parser.SIMULATION_UNIT_INIT));
                    System.out.println("Convert the Formula into ABSL \n"+get(Parser.SIMULATION_UNIT_INIT));

                       
	
		}
		if(def!=null){
			System.out.println("Initial Formula\t"+get(Parser.SIMULATION_UNIT_DEF));
			set(Parser.SIMULATION_UNIT_DEF,evaluate(model,def));
                        System.out.println("Convert the Formula into ABSL \n"+get(Parser.SIMULATION_UNIT_DEF));
			
		}
	}


	private static final String REGEXP="^(" +
			"FOR\\((\\w+)=(\\d+)\\.\\.(\\d+)\\||" + // For Loop
			"[a-zA-Z_$]+\\(|" + // Function
			//"[a-zA-Z]|" + // Function
			"([a-zA-Z_$][a-zA-Z_$0-9]+)|(\\'[^\\']+\\')|[a-zA-Z]|"+ // Variable
			"(\\d+\\.?\\d*)|" + // Constant
			"(\\<\\<[^\\>]+\\>\\>)|" +// Unit
			"(\\>=|\\<=|\\<\\>|==|=|\\>|\\<|\\(|\\)|\\[|\\]|\\{|\\}|,|\\+|\\-|\\*|/|\\\\|\\^|!|%))";
	private static final String REGEXP_VARIABLE="^([a-zA-Z_$][a-zA-Z_$0-9]+|(\\'[^\\']+\\'))|[a-zA-Z]$";
	private static final String REGEXP_CONST="^\\d+\\.?\\d*$";
	private static final String REGEXP_UNIT="^\\<\\<[^\\>]+\\>\\>$";
	private static final String REGEXP_LOOP="^FOR\\((\\w+)=(\\d+)\\.\\.(\\d+)\\|$";


	public void parse(String name,List<String> rpn,List<String> variables) throws ParseException{
		String function=get(name);
		if(function==null) return;


		Stack<String> stack=new Stack<String>();
		for(int i=0;i<function.length();i++){
			String actual=function.substring(i,i+1);
			if("(".equals(actual) || "{".equals(actual) || "[".equals(actual))
				stack.push(actual);
			if(")".equals(actual) || "}".equals(actual) || "]".equals(actual)){
				String test=stack.pop();
				if(!(")".equals(actual) && test.equals("(") || "}".equals(actual) && test.equals("{") || "]".equals(actual) && test.equals("[")))
					throw new ParseException("allgemeiner Klammerfehler "+function,this); 
			}
		}
		if(!stack.empty()) throw new ParseException("allgemeiner Klammerfehler",this);		
		Pattern pattern=Pattern.compile(REGEXP);
		boolean lastTokenWasUnit=false;
		Matcher test;
		int level=0;
		List<String> tokens=new Vector<String>();
		while (function.length()>0){
			String found;
			test=pattern.matcher(function);
			if(test.lookingAt()){
				found=test.group();				
				function=function.substring(found.length());				
				if(found.matches(REGEXP_LOOP)){
					
					tokens.add("FOR(\"i\",1,10,");
					lastTokenWasUnit=false;
				}
				else if(found.matches(REGEXP_VARIABLE)){					

					found=prefix+found.substring(1, found.length()-1);
					tokens.add(found);
					
					if(!variables.contains(found))// && !Parser.SIMULATION_UNIT_NATURE_LEVEL.equals(get(Parser.SIMULATION_UNIT_NATURE))
						variables.add(found);
					lastTokenWasUnit=true;
				}
				else if(found.matches(REGEXP_CONST)){
					tokens.add(prefix+found);
					
					lastTokenWasUnit=true;
				}
				else if((found.equals("+") || found.equals("-")) && lastTokenWasUnit==false){
					tokens.add(found+found);//sign					
					lastTokenWasUnit=false;
				}
				else if(found.matches(REGEXP_UNIT)){
//					int position=tokens.size()-1;
//					String tempt=tokens.get(position);
//					while(position>0){
//						if(tokens.get(position).endsWith("(")) level++;
//						if(tokens.get(position).equals(")")) level--;
//						if(level==0) break;
//						position--;
//						
//					}
//					
//					System.out.println("position: "+found);
//					while(position>0 && (tokens.get(position-1).equals("--") || tokens.get(position-1).equals("++")))
//						position--; // Vorzeichen einbeziehen
//				    tokens.add(position,"UNIT(");
//					tokens.add(position,"=");
					
//					tokens.add(position,"(");
//				    position--; 
//					position++;
//				found=prefix+"\""+found.substring(2, found.length()-2)+"\"";
//				tokens.add(position,found);
//				position++;
//				tokens.add(position,"=");
//					found=found.substring(2, found.length()-2);
//					tokens.add(",");
//					tokens.add(position,found);
//					position++;
//					tokens.add(position,"=");
//					tokens.add(tempt);
//					tokens.add(")");
//					System.out.print("PRINT OUT THE TOKEN"+tokens);
					lastTokenWasUnit=true;
				}
				else if(found.equals("[")){
					tokens.add("INDEX(");
					lastTokenWasUnit=false;
				}
				else if(found.equals("{")){
                                    tokens.add("(");
//					tokens.add("ARRAY(");
//                                        System.out.print("array token"+tokens);
					lastTokenWasUnit=false;
				}
				else if(found.equals("}") || found.equals("]") || found.equals(")")){
					tokens.add(")");
					lastTokenWasUnit=true;
				}
				else{
					tokens.add(found);
					lastTokenWasUnit=false;
				}
			}
			else{
				found=function.substring(0,1);
				function=function.substring(1);
				throw new ParseException("Unbekanntes Zeichen: \""+found+"\"",this);
			}
		}

	  	stack.clear();

	  	for (int i=0;i<tokens.size();i++){
	  		String actual = tokens.get(i);
	  		if (actual.startsWith(prefix)){
	  			rpn.add(actual); 
	  		}
	  		else{
	  			if (actual.endsWith("(") || actual.startsWith("FOR("))
	  				stack.push(actual);
	  			else if (")".equals(actual) && !stack.empty()){
	  				while (!stack.peek().endsWith("(") && !stack.peek().startsWith("FOR(")){
	  					rpn.add(stack.pop());
	  					if (stack.empty()) throw new ParseException("Klammerfehler",this);
	  				}
	  				if(stack.peek().equals("("))
	  					stack.pop();
	  				else
	  					rpn.add(stack.pop());
	  			}
	  			else if (!actual.endsWith("(") && !")".equals(actual)){
		  			while (!stack.empty() &&  getPri(stack.peek()) >= getPri(actual)){
		  				rpn.add(stack.pop());
		  			}
		  			stack.push(actual);
		  		}
	  		}
	  	}

	  	while (!stack.empty()){
	  		if(stack.peek().equals("("))
	  			throw new ParseException("Klammerfehler",this);
	  		rpn.add(stack.pop());
	  	}

	}
	public String evaluate(Hashtable<String,ParsedUnit> model,List<String> rpn) throws ParseException{

		Stack<String> stack=new Stack<String>();
		Stack<String> units=new Stack<String>();
                String copy;
                
                int cou_max=0;
                int cou_min=0;
		try{
			
		String operand,actualunit;
	  	for(int i=0;i<rpn.size();i++){
                   
	  		String actual = rpn.get(i);
	  		if(actual.startsWith(prefix)){
	  			 actual=actual.substring(prefix.length());
	  			 if(actual.charAt(0)=='\"'){
	  				 stack.push(actual);			
					 if(withUnits)
						 units.push("1");
					 
	  			 }
	  			
	  			else if(actual.matches(REGEXP_VARIABLE)){
	  				 stack.push(actual);
					 if(withUnits)
						 units.push("1");
	  			}
	  			 else if(actual.matches(REGEXP_CONST)){
	  				stack.push(actual);
					 if(withUnits)
						 units.push("1");
					 
	  			 }
	  			 else if(actual.matches("NAN")){
	  				 stack.push("Double.NaN");
					 if(withUnits)
						 units.push("1");
					 
	  			 }
	  			
	  			
	  			 else{
	  				 if(model!=null && model.containsKey(actual)){
	  					 if(model.get(actual).get(Parser.SIMULATION_UNIT_TYPE)!=null){

	  						String type=model.get(actual).get(Parser.SIMULATION_UNIT_TYPE);
	  						if("1".equals(type)){
	  							stack.push("variables.getDouble(\""+actual+"\")");
	  						}
	  						else if("1[]".equals(type)){
	  							String dim=model.get(actual).get(Parser.SIMULATION_UNIT_DIM);
	  							stack.push("variables.getDoubleRange(\""+actual+"\","+dim+")");
	  						}
	  						else if("bool".equals(type)){
	  							stack.push("variables.getBoolean(\""+actual+"\")");
	  						}
	  						else if("bool[]".equals(type)){
	  							String dim=model.get(actual).get(Parser.SIMULATION_UNIT_DIM);
	  							stack.push("variables.getBooleanRange(\""+actual+"\","+dim+")");
	  						}
	  					 }
	  			 	}
				 }

	  		}
			else{
				if(actual.equals("(")) // nutzlose Klammer
					continue;
				else if(actual.equals("RANDOM(") || actual.equals("NORMAL(") || actual.equals("TIMESTEP(")){
					stack.push(actual+")");
					if(withUnits)
						units.push("1");
					continue;
				}
				operand=stack.pop();
				if(withUnits)
					actualunit=units.pop();

				else if(actual.equals("ARRAY(")){
                                    String[] operanden=intelliSplit(operand,',');
                                    System.out.println(operand);

                                    for(int j=0;j<operanden.length;j++){
						operand+=operanden[j];

                                    }
                                    stack.push(operand);

					if(withUnits){
						String[] actualunits=actualunit.split("\\,");
						for(int j=1;j<actualunits.length;j++)
							if(!actualunits[0].equals(actualunits[j]))
								throw new ParseException("Unvalid Einheit: unit* erwartet, "+actualunit+" gefunden!",this);
						units.push(actualunits[0]+"[]");
					}
				}
				else if(actual.equals("INDEX(")){
					stack.push(stack.pop()+"[(int)"+operand+"-1]");
					if(withUnits){
						if(!actualunit.equals("1"))
							throw new ParseException("Unvalid Index: 1 erwartet, "+actualunit+" gefunden!",this);
						actualunit=units.pop();
						if(!actualunit.endsWith("[]"))
								throw new ParseException("Unvalid Unit: unit[] erwartet, "+actualunit+" gefunden!",this);
						units.push(actualunit.substring(0,actualunit.length()-2));
					}
				}
				else if(actual.equals("INTEGRATION(")){
					if(operand.indexOf('\"')>-1){
			  			String test=operand.substring(operand.indexOf('\"')+1,operand.lastIndexOf('\"'));
			  			if(model!=null && model.containsKey(test) && Parser.SIMULATION_UNIT_INTEGRATION_ZEROORDER.equals(model.get(test).get(Parser.SIMULATION_UNIT_INTEGRATION))){
		  					 //Zeroorder
			  				 stack.push(operand);
		  					 if(withUnits)
		  						 units.push(actualunit);
			  			 }
		  				 else if(model!=null && model.containsKey(test) && Parser.SIMULATION_UNIT_INTEGRATION_FIRSTORDER.equals(model.get(test).get(Parser.SIMULATION_UNIT_INTEGRATION))){
		  					  //Firstorder TODO
			  					stack.push("MULT("+operand+",TIMESTEP())");
			 					if(withUnits)
			 						units.push(evalUnit(actualunit+"*yr"));
			  			 }
		  				 else{
		  				
			  				stack.push("MULT("+operand+",TIMESTEP())");
			 				if(withUnits)
			 					units.push(evalUnit(actualunit+"*yr"));
		  				 }
			  		}
			  		else if(withUnits)
			  			throw new ParseException("Unvalid Integration: unit erwartet, "+actualunit+" gefunden!",this);
			  		else throw new ParseException("Unvalid Integration!",this);
				}
	  			else if(actual.startsWith("FOR(")){
	  				stack.push(actual+operand+")");
	  				if(withUnits){
	  					if(actualunit.contains("[]"))
	  						throw new ParseException("Unvalid Einheit: "+actualunit.replace("[]", "[]")+" erwartet, "+actualunit+" gefunden!",this);
	  					units.push(actualunit+"[]");
	  				}
				}
				else if("MIN(".equals(actual)){
				        cou_min++;
					String[] operanden=intelliSplit(operand,',');                             
                                        if(operanden[0].startsWith("var")){
                                            operand=operanden[0];
                                            stack.push(operand);
                                            operanden[0]=operanden[0].substring(4, 10);
                                        }
                                        if(operanden[1].startsWith("var")){
                                            if(operanden[0].startsWith("var")){
                                                operand+=operanden[1];
                                                stack.push(operand);
                                                operanden[1]=operanden[1].substring(4, 10); }
                                            else {
                                                operand=operanden[1];
                                                stack.push(operand);
                                                operanden[1]=operanden[1].substring(4, 10); 
                                            }
                                            }
                                    
                                        if(operanden[0].startsWith("var")||operanden[1].startsWith("var"))
                                            operand+="var min_v"+cou_min+"=0;\r\n";
                                        else operand="var min_v"+cou_min+"=0;\r\n";
                                             operand+="if("+operanden[0]+"<"+operanden[1]+")\r\n";
					operand+="{ min_v"+cou_min+"="+operanden[0]+"; }\r\n";
					operand+="else{ min_v"+cou_min+"="+operanden[1]+"; }\r\n";
                                      	stack.push(operand);                                    
				
					if(withUnits){
						String[] actualunits=actualunit.split("\\,");
						for(int j=1;j<actualunits.length;j++)
							if(!actualunits[0].equals(actualunits[j]))
								throw new ParseException("Unvalid Einheit:unit* erwartet, "+actualunit+" gefunden!",this);
						units.push(actualunit);
					}
				}
				else if("MAX(".equals(actual)){
                                            cou_max++;     
  
                                            String[] operanden=intelliSplit(operand,',');                             
                                        if(operanden[0].startsWith("var")){
                                            operand=operanden[0];
                                            stack.push(operand);
                                            operanden[0]=operanden[0].substring(4, 10);
                                        }
                                        if(operanden[1].startsWith("var")){
                                            if(operanden[0].startsWith("var")){
                                                operand+=operanden[1];
                                                stack.push(operand);
                                                operanden[1]=operanden[1].substring(4, 10); }
                                            else {
                                                operand=operanden[1];
                                                stack.push(operand);
                                                operanden[1]=operanden[1].substring(4, 10); 
                                            }
                                            }
                                    
                                        if(operanden[0].startsWith("var")||operanden[1].startsWith("var"))
                                            operand+="var max_v"+cou_max+"=0;\r\n";
                                        else operand="var max_v"+cou_max+"=0;\r\n";
                                             operand+="if("+operanden[0]+">"+operanden[1]+")\r\n";
					operand+="{ max_v"+cou_max+"="+operanden[0]+"; }\r\n";
					operand+="else{ max_v"+cou_max+"="+operanden[1]+"; }\r\n";
					stack.push(operand);
					if(withUnits){
						String[] actualunits=actualunit.split("\\,");
						for(int j=1;j<actualunits.length;j++)
							if(!actualunits[0].equals(actualunits[j]))
								throw new ParseException("Unvalid Einheit:unit* erwartet, "+actualunit+" gefunden!",this);
						units.push(actualunit);
					}
				}
				else if("IF(".equals(actual)){
					
					String[] operanden=intelliSplit(operand,',');
                                        System.out.println(operanden[0]);
					operand="if("+operanden[0]+")\r\n";
					operand+="{ return "+operanden[1]+"; }\r\n";
					operand+="else{ return "+operanden[2]+"; }\r\n";
                                       
					stack.push(operand);
			
				}
                                else if("INIT".equals(actual)){
					
					 System.out.println("yes come here"+operand);
			
				}
                                else if("ARRSUM(".equals(actual)){
					
					String[] operanden=intelliSplit(operand,',');
                                        operand=operanden[0];
                                        for(int j=1;j<operanden.length;j++){                                          
                                            operand+="+"+operanden[j];                                        	
                                        }
                                        System.out.println("what is it"+operand);
					stack.push(operand);
				
				}
                                 else if("DIVZX(".equals(actual)){
					
					String[] operanden=intelliSplit(operand,',');
					operand="if("+operanden[1]+"!=0)\n";
					operand=operand+"{ return "+operanden[0]+"/"+operanden[1]+"; }\n";
					operand=operand+"else{ return "+operanden[2]+"; }\n";		
					stack.push(operand);
				
				}
                                  else if("SQRT(".equals(actual)){
					double org,result;  
					String[] operanden=intelliSplit(operand,',');
                                         ArrayList al=new ArrayList();
                                        
                                        operand="(";
                                    for (String operanden1 : operanden) {
                                        org = Double.parseDouble(operanden1);
                                       
                                      result=Math.sqrt(org);
                                      result=Math.floor(result);
                                      al.add(result);                   
                                                  
                                    }
                                   Collections.sort(al,Collections.reverseOrder());
                                                               
                                    for(int k=0;k<al.size()-1;k++){
                                      operand+=al.get(k).toString()+",";
                                    }
                                     operand+=al.get(al.size()-1);
                                
						operand+=")";
					stack.push(operand);				
				}
                                   else if("EXP(".equals(actual)){
                                       double result;
                                       String[] operanden=intelliSplit(operand,',');                                    
                                        operand="({";
                                        for(int k=0;k<operanden.length-1;k++){
                                           result=Math.exp(Double.parseDouble(operanden[k]));
                                           operand+=Double.toString(result)+",";
                                        }
                                        result=Math.exp(Double.parseDouble(operanden[operanden.length-1]));
                                        operand+=Double.toString(result);
                                        operand+="})";
                                        stack.push(operand);
                                   }
                                     else if("LOG(".equals(actual)){
                                       double result,int_b,int_a;
                                       String[] operanden=intelliSplit(operand,','); 
                                       if(operanden.length<2){
                                           int_b=Double.parseDouble(operanden[0]);
                                           int_a=10;
                                       }
                                       else{
                                        int_b=Double.parseDouble(operanden[0]);
                                        int_a=Double.parseDouble(operanden[1]);
                                       }
                                           result=Math.log(int_b)/Math.log(int_a);
                                           operand=Double.toString(result);
                                       
                                        stack.push(operand);
                                   }
                                
                                
                                
				else if(actual.endsWith("(")){

					stack.push(actual+operand+")");
					if(withUnits){
						String[] actualunits=actualunit.split("\\,");
						if(actual.equals("IF(")){
							if(actualunits.length==3 && actualunits[0].equals("bool") && actualunits[1].equals(actualunits[2]))
								{
								units.push(actualunits[1]);
								System.out.println("Print the if unit"+actualunits[1]);
								System.out.println("Print the if unit"+actualunits[0]);
								System.out.println("Print the if unit"+actualunits[2]);
								System.out.println("MARKED");
								}
							  
							
							else
								throw new ParseException("Unvalid Einheit: bool,unit,unit erwartet, "+actualunit+" gefunden!",this);
						}
						else if(actual.equals("DIVZX(")){
							if(actualunits.length==3 && actualunits[0].equals(actualunits[1]) && actualunits[1].equals(actualunits[2]))
								units.push(actualunits[1]);
							else
								throw new ParseException("Unvalid Einheit: unit,unit,unit erwartet, "+actualunit+" gefunden!",this);
						}
						else{
							System.err.println(actual);
							units.push(actualunit);
						}
					}
				}

				else if("%".equals(actual)){

                                    stack.push(stack.pop()+"%"+operand);
	  				if(withUnits)
	  					units.push(actualunit);
				}
				else if("--".equals(actual)){
	  				stack.push("NEG("+operand+")");
	  				if(withUnits)
	  					units.push(actualunit);
				}
				else if("++".equals(actual)){
	  				stack.push("POS("+operand+")");
	  				if(withUnits)
	  					units.push(actualunit);
				}
				else if("*".equals(actual)){
                                    stack.push(stack.pop()+"*"+operand);
	  				if(withUnits)
	  					units.push(evalUnit(units.pop()+"*"+actualunit));
				}
				else if("^".equals(actual)){
	  				stack.push("POW("+stack.pop()+","+operand+")");
	  				if(withUnits)
	  					units.push(evalUnit(units.pop()+"^"+actualunit));
				}
	  			else if("/".equals(actual)){

  				stack.push(stack.pop()+"/"+operand);
	  				
	  				if(withUnits)
	  					units.push(evalUnit(units.pop()+"/"+actualunit.replaceAll("/", "//").replaceAll("\\*", "/").replaceAll("//", "\\*")));

	  			}
	  			else if("\\".equals(actual)){
	  				stack.push("DIV("+operand+","+stack.pop()+")");
	  				if(withUnits)
	  					units.push(evalUnit(actualunit+"/"+units.pop().replaceAll("/", "//").replaceAll("\\*", "/").replaceAll("//", "\\*")));
	  			}
	  			else if("+".equals(actual)){
	  				
	  				stack.push(stack.pop()+"+"+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.peek().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push(units.pop());
	  			}
	  			else if("-".equals(actual)){	  				
	  				stack.push(stack.pop()+"-"+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.peek().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push(units.pop());
	  			}
	  			else if("<".equals(actual)){

                                    stack.push(stack.pop()+"<"+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit:"+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if(">".equals(actual)){
                                     stack.push(stack.pop()+">"+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if("<=".equals(actual)){
	  				stack.push(stack.pop()+"<="+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if(">=".equals(actual)){
                                    stack.push(stack.pop()+">="+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit:"+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if("<>".equals(actual)){
                                    stack.push(stack.pop()+"!="+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit:"+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if("==".equals(actual)){
                                    stack.push(stack.pop()+"=="+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("bool");
	  			}
	  			else if("=".equals(actual)){
	  				stack.push(stack.pop()+"="+operand);
	  				if(withUnits)
	  					if(units.empty() || !units.pop().equals(actualunit))
	  						throw new ParseException("Unvalid Einheit: "+actualunit+" erwartet, "+units.peek()+" gefunden!",this);
	  					else
	  						units.push("");
	  			}
	  			else if(",".equals(actual)){

	  				stack.push(stack.pop()+","+operand);

	  				if(withUnits)
	  					units.push(units.pop()+","+actualunit);
	  			}
			
	  			else{
	  				new ParseException("Unvalid Einheit: "+actual,this);
	  			}
	  		}

	  	}

                copy=stack.get(0);
              for(int i=1;i<stack.size();i++){
                  copy+=stack.get(i);
                 
              }
//               System.out.println("output"+copy);
//		return stack.pop();
               return copy;
                
	   
		
		}
		catch(java.util.EmptyStackException e){
			throw new ParseException("Unvalid Notation",this);
		}
		catch(NullPointerException e){throw new ParseException("Unvalid Argument",this);}
	}
        



  	private int getPri(String x){
  		if(x.equals("^")) return 7;
  		if(x.equals("!") || x.equals("++") || x.equals("--")) return 6;
  		if(x.equals("*") || x.equals("/") || x.equals("^")) return 5;
  		if(x.equals("+") || x.equals("-")) return 4;
  		if(x.equals(">=") || x.equals("<=") || x.equals("<>") || x.equals("==") || x.equals(">") || x.equals("<") || x.equals("=") || x.equals(",")) return 3;
  		if(x.endsWith("(")) return 2;
  		if(x.equals(")")) return 1;
  		return 0;
	}
  	private String[] intelliSplit(String text, char test) throws ParseException{
		ArrayList<String> list=new ArrayList<String>();
		Stack<Character> stack=new Stack<Character>();
		StringBuffer buff=new StringBuffer();
		for(int i=0;i<text.length();i++){
			char act=text.charAt(i);
			if(act==test && stack.empty()){
				list.add(buff.toString());
				buff=new StringBuffer();
			}else{
				if(act=='\"')
					if(!stack.empty() && stack.peek().charValue()=='\"')
						stack.pop();
					else
						stack.push(act);
				else if(act=='(' || act=='[' || act=='{')
					stack.push(act);
				else if(act==')' || act==']' || act=='}')
					if(!stack.empty() &&(
						(act==')' && stack.peek().charValue()=='(') ||
						(act==']' && stack.peek().charValue()=='[') ||
						(act=='}' && stack.peek().charValue()=='{')))
						stack.pop();
					else throw new ParseException("Klammerfehler");
				buff.append(act);
			}
		}
		if(buff.length()>0)
			list.add(buff.toString());
		if(!stack.empty())
			throw new ParseException("Klammerfehler");
		String[] result=new String[list.size()];
		for(int i=0;i<list.size();i++)
			result[i]=list.get(i);
		return result;
  	}
  	private String evalUnit(String unit){
  		unit.replace("Â²", "^2").replaceAll("Â³", "^3");
  		Vector<String> numerator=new Vector<String>();
  		Vector<String> denominator=new Vector<String>();
  		boolean isNumerator=true;
  		String temp="";
  		for(int i=0;i<unit.length();i++){
  			if(unit.charAt(i)=='*' || unit.charAt(i)=='/'){
  				// Faktor hinzufÃ¼gen
  				if(isNumerator && !temp.equals("1"))
  					if(denominator.contains(temp))
  						denominator.remove(temp);
  					else
  						numerator.add(temp.toString());
  				else if(!isNumerator && !temp.equals("1"))
  					if(numerator.contains(temp))
  						numerator.remove(temp);
  					else
  						denominator.add(temp);
  				temp="";
  				isNumerator=(unit.charAt(i)=='*');
  			}
  			else if(unit.charAt(i)=='^'){
  				int n=unit.length();
  				if(unit.indexOf('*',i)>-1) n=Math.min(n, unit.indexOf('*',i));
  				if(unit.indexOf('/',i)>-1) n=Math.min(n, unit.indexOf('/',i));
  				int exponent=Integer.parseInt(unit.substring(i+1,n));
  				if(exponent<0){
  					// Kehrbruch
  					exponent*=-1;
  					isNumerator=!isNumerator;
  				}
  				// Exponent konvertieren
  				for(int j=0;j<exponent;j++){
  					if(isNumerator)
  						unit=unit.substring(0,i)+"*"+temp;
  					else
  						unit=unit.substring(0,i)+"/"+temp;
  					if(n!= unit.length())
  						unit+=unit.substring(n);
  				}
  				if(isNumerator && !temp.equals("1"))
  					if(denominator.contains(temp))
  						denominator.remove(temp);
  					else
  						numerator.add(temp);
  				else if(!isNumerator && !temp.equals("1"))
  					if(numerator.contains(temp))
  						numerator.remove(temp);
  					else
  						denominator.add(temp);
  				temp="";
  				i=n;
  			}
  			else{
  				temp+=unit.charAt(i);
  			}
  		}
  		// letzer Faktor
  		if(temp.length()>0 && !temp.equals("1"))
  			if(isNumerator)
				numerator.add(temp);
			else
				denominator.add(temp);
    	// Einheit generieren
  		if(numerator.size()>0)
  			unit=numerator.get(0);
  		else
  			unit="1";
  		for(int i=1;i<numerator.size();i++)
  			unit+="*"+numerator.get(i);
  		for(int i=0;i<denominator.size();i++)
  			unit+="/"+denominator.get(i);
  		return unit;
  	}
	public static void main(String args[]) throws ParseException{
	
		logger.setLevel(Level.ALL);
		Logger root = Logger.getLogger("");
		root.setLevel(Level.ALL);
		Handler[] handlers = root.getHandlers();
		for(int i = 0; i < handlers.length; i++)
			root.removeHandler(handlers[i]);

test("MIN(it_hw_server,MIN(0<<MIPS>>,it_hw_server_scrap))");
	}
	public static void test(String test) throws ParseException{
		ParsedFormula unit=new ParsedFormula();
		unit.parsed=new Hashtable<String,String>();
		unit.set(Parser.SIMULATION_UNIT_DEF,test);
		unit.set(Parser.SIMULATION_UNIT_INIT,test);
		unit.parseFormula();
		System.out.println(Parser.SIMULATION_UNIT_DEF);
	}
}
